import { UITransform, instantiate, RichText, tween, v3, Tween, UIOpacity } from "cc";
import { ToastNoticeProxy } from "../../script/proxy/ToastNoticeProxy";
import { bind } from "../../core/module/proxy/ProxyDecorator";
import { UIBase } from "../../core/module/ui/UIBase";

@bind(ToastNoticeProxy)
export class ToastNotice extends UIBase<ToastNoticeProxy> {
    readonly fadeTime: number = 1;
    readonly tolerance: number = 50;
    readonly speed: number = 100;

    private _noticeMsgQueue: { msg: string, times: number }[] = [];
    /**
     * 0 未显示
     * 1 显示中
     * 2 播放中
     * 3 关闭中
     * 4 下一个
     */
    private status: number = 0;

    onShow(): void {
        super.onShow();
        const msg = this.args.msg || '';
        const times = this.args.times || 1;
        this._showNotice(msg, times)
    }


    /**
     * 显示公告
     * @param msg 公告内容
     * @param times 循环次数
     */
    private _showNotice(msg: string, times: number = 1) {
        let t = times < 1 ? 1 : times;
        this._noticeMsgQueue.push({ msg, times: t });
        this._playNotice();
    }

    private async _playNotice() {
        if (this._noticeMsgQueue.length <= 0) {
            this._playHideNotice()
            return
        }
        await this._playShowNotice()

        const data = this._noticeMsgQueue.shift();
        const width = this._view.main.getComponent(UITransform).width;
        const item = instantiate(this._view.item)
        item.setParent(this._view.mask)
        item.setPosition(width / 2 + this.tolerance, 0)
        item.active = true;

        const richText = item.getComponent(RichText)
        richText.string = data.msg
        // 下一帧等待富文本渲染完成
        this._view.scheduleOnce(() => {
            const richWidth = richText.getComponent(UITransform).width
            const movetime = (richWidth + width + 2 * this.tolerance) / this.speed
            tween(item)
                .call(() => item.setPosition(width / 2, 0))
                .to(movetime, { position: v3(-richWidth - width / 2 - this.tolerance) }, { easing: 'linear' })
                .union()
                .repeat(data.times)
                .call(() => {
                    item.destroy()
                    this.status = 4
                    this._playNotice()
                })
                .start()
        })
    }



    private _playHideNotice() {
        // 未显示或正在关闭
        if (this.status == 0 || this.status == 3) return
        // 正显示显示关闭动画
        if (this.status == 1) Tween.stopAllByTarget(this._view.main)

        this.status = 3;
        const uiOpacity = this._view.main.getComponent(UIOpacity)
        tween(uiOpacity)
            .to(this.fadeTime, { opacity: 0 })
            .call(() => {
                this.status = 0;
                this._view.main.active = false;
            })
            .start()
    }

    private _playShowNotice() {
        return new Promise<void>((resolve, reject) => {
            // 正在显示或者已显示
            if (this.status == 1 || this.status == 2) return
            const uiOpacity = this._view.main.getComponent(UIOpacity)
            // 未显示
            if (this.status == 0) {
                this.status = 1;
                this._view.main.active = true;
                uiOpacity.opacity = 0
            }

            // 正在关闭
            if (this.status == 3)
                Tween.stopAllByTarget(uiOpacity)

            // 显示下一个
            if (this.status == 4) {
                this.status = 2
                resolve()
                return
            }

            this.status = 1;
            tween(uiOpacity)
                .to(this.fadeTime, { opacity: 255 })
                .call(() => {
                    this.status = 2;
                    resolve()
                })
                .start()

        })
    }
}